home *** CD-ROM | disk | FTP | other *** search
- #import "PControl.h"
- #import "Plot3DView.h"
- #import "PlotShape.h"
- #import <appkit/appkit.h>
- #import <dpsclient/event.h>
- #import <dpsclient/psops.h>
- #import <appkit/color.h>
- #import <stdio.h>
- #import <math.h>
- #import <ctype.h>
- #include <libc.h>
- #import "Expression.h"
- #import "DensView.h"
-
- int comp(float *x,float *y);
-
- @implementation PControl
- -init
- {
- [super init];
- return self;
- }
-
- /* Called once by the Plot3DView to do initialization and pass pref pointer */
- -startup:(SetPref *)Pref
- {
- pref=Pref;
- /* display initial preferences settings */
- curPref=0;
- bpath=(char *)[[NXBundle mainBundle] directory];
- [symsel selectCellWithTag:pref[0].sym+1];
- equation=[equation docView];
- [equation setText:[pref[0].expr text]];
- /* make sure plot agrees with displayed min/max values */
- [gridx setIntValue:pref[curPref].nx];
- [gridy setIntValue:pref[curPref].ny];
- [d3View zoomTo:[minX floatValue] :[minY floatValue] :[maxX floatValue] :[maxY floatValue]];
- [d3View setDelegate:self];
- /*[self readFile:self];*/
-
- I_lim=[I_lim contentView];
- I_dis=[I_dis contentView];
- I_pho=[I_pho contentView];
- return self;
- }
-
- /* display preferences for a data set */
- -disPref:sender
- {
- int i;
- curPref=[[sender selectedCell] tag];
- [symsel selectCellWithTag:pref[curPref].sym+1];
- [color1 setColor:NXConvertRGBToColor(pref[curPref].mapcol[0][0],
- pref[curPref].mapcol[0][1],pref[curPref].mapcol[0][2])];
- [color2 setColor:NXConvertRGBToColor(pref[curPref].mapcol[1][0],
- pref[curPref].mapcol[1][1],pref[curPref].mapcol[1][2])];
- [color3 setColor:NXConvertRGBToColor(pref[curPref].mapcol[2][0],
- pref[curPref].mapcol[2][1],pref[curPref].mapcol[2][2])];
- [color4 setColor:NXConvertRGBToColor(pref[curPref].mapcol[3][0],
- pref[curPref].mapcol[3][1],pref[curPref].mapcol[3][2])];
- [color5 setColor:NXConvertRGBToColor(pref[curPref].mapcol[4][0],
- pref[curPref].mapcol[4][1],pref[curPref].mapcol[4][2])];
-
- [colortype selectCellWithTag:pref[curPref].mapmode];
-
- for (i=0; i<5; i++)
- [[colorsel cellAt:0 :i] setIntValue:pref[curPref].mapsel[i]];
-
- if (pref[curPref].fileData==NULL) [ffSel selectCellWithTag:0];
- else [ffSel selectCellWithTag:1];
- [equation setText:[pref[curPref].expr text]];
- [gridx setIntValue:pref[curPref].nx];
- [gridy setIntValue:pref[curPref].ny];
- [d3View zoom:self];
- return self;
- }
-
- /* put preferences from screen into SetPref for curPref set */
- -stoPref:sender
- {
- char *tmp;
- int i,j,k;
- pref[curPref].sym=[[symsel selectedCell] tag]-1;
- pref[curPref].nx=[gridx intValue];
- if (pref[curPref].nx>MAXGRID||pref[curPref].nx<4)
- [gridx setIntValue:pref[curPref].nx=10];
- pref[curPref].ny=[gridy intValue];
- if (pref[curPref].ny>MAXGRID||pref[curPref].ny<4)
- [gridy setIntValue:pref[curPref].ny=10];
- tmp=malloc([equation textLength]+50);
- [equation getSubstring:tmp start:0 length:[equation textLength]+1];
- /* Fix equation for parsing */
- k=strlen(tmp);
- for (i=0; i<k; i++) {
- if (tmp[i]=='[') tmp[i]='(';
- if (tmp[i]==']') tmp[i]=')';
- if (isupper(tmp[i])) tmp[i]=tolower(tmp[i]);
- if ((tmp[i]=='+'||tmp[i]=='-')&&(isdigit(tmp[i+1])||tmp[i+1]=='.')) {
- for (j=k; j>i; j--) tmp[j+1]=tmp[j];
- tmp[i+1]=' ';
- k++;
- }
- }
-
- /* if the equation doesn't parse, set it to 0 */
- if (strlen(tmp)==0 ||
- [pref[curPref].expr parse:tmp]==0) {
- [self error:"Cannot parse equation!"];
- [pref[curPref].expr parse:"0"];
- }
-
- /* Colors */
- NXConvertColorToRGB([color1 color],&pref[curPref].mapcol[0][0],
- &pref[curPref].mapcol[0][1],&pref[curPref].mapcol[0][2]);
- NXConvertColorToRGB([color2 color],&pref[curPref].mapcol[1][0],
- &pref[curPref].mapcol[1][1],&pref[curPref].mapcol[1][2]);
- NXConvertColorToRGB([color3 color],&pref[curPref].mapcol[2][0],
- &pref[curPref].mapcol[2][1],&pref[curPref].mapcol[2][2]);
- NXConvertColorToRGB([color4 color],&pref[curPref].mapcol[3][0],
- &pref[curPref].mapcol[3][1],&pref[curPref].mapcol[3][2]);
- NXConvertColorToRGB([color5 color],&pref[curPref].mapcol[4][0],
- &pref[curPref].mapcol[4][1],&pref[curPref].mapcol[4][2]);
-
- for (i=0; i<5; i++) pref[curPref].mapsel[i]=[[colorsel cellAt:0 :i] intValue];
-
- pref[curPref].mapmode=[[colortype selectedCell] tag];
-
- /* if spherical plot, set proper limits */
- if (pref[curPref].sym==6) {
- [minX setFloatValue:0];
- [maxX setFloatValue:M_PI];
- [minY setFloatValue:0];
- [maxY setFloatValue:M_PI*2.0];
- [self setMinMax:self];
- }
- [d3View zoom:self];
- return self;
- }
-
- /* Read 3d data from a file and put it into the current data set */
- /* does NOT wait for an "OK" press, like other prefs */
- -readFile:sender
- {
- id panel;
- int i,j,k,cc=0,nx,ny;
- char s[201],sc[20];
- FILE *in;
- float x0,y0,z0,z1,f,x[MAXGRID+1],y[MAXGRID+1];
- Point *p;
-
- if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].
- fileData=NULL; }
-
- if (sender!=self) {
- /* get a filespec from the user */
- panel=[[OpenPanel new] allowMultipleFiles:NO];
- if (![panel runModalForTypes:NULL]) {
- [ffSel selectCellWithTag:0];
- [equation setText:"0"];
- [pref[curPref].expr parse:"0"];
- return self;
- }
-
- /* if we can't open the file, go back to equation mode */
- in=fopen([panel filename],"r");
- }
- else {
- [ffSel selectCellWithTag:1];
- sprintf(s,"%s/title.3d",bpath);
- in=fopen(s,"r");
- }
-
- if (fgets(s,200,in)==NULL) {
- [ffSel selectCellWithTag:0];
- [equation setText:"0"];
- [pref[curPref].expr parse:"0"];
- [self error:"Can't open file."];
- return self;
- }
-
- /* ignore leading # lines */
- while (s[0]=='#') { fgets(s,80,in); cc++; }
-
- /* accept either "x,y,z\n" or "x y z\n" files */
- strcpy(sc," %f , %f , %f");
- if (sscanf(s,sc,&x[0],&y[0],&z0)!=3) {
- strcpy(sc," %f %f %f");
- if (sscanf(s,sc,&x[0],&y[0],&z0)!=3) {
- [ffSel selectCellWithTag:0];
- [equation setText:"0"];
- [pref[curPref].expr parse:"0"];
- [self error:"File not in 'x y z' or 'x,y,z' format."];
- return self;
- }
- }
- z1=z0;
-
- /* count the number of points in the file */
- nx=ny=1;
- while (fscanf(in,sc,&x[nx],&y[ny],&f)==3) {
- if (f<z0) z0=f;
- for (i=0; i<nx; i++) if (x[nx]==x[i]) break;
- if (i==nx) nx++;
- for (i=0; i<ny; i++) if (y[ny]==y[i]) break;
- if (i==ny) ny++;
- if (nx==MAXGRID+1||ny==MAXGRID+1) {
- [ffSel selectCellWithTag:0];
- [equation setText:"0"];
- [pref[curPref].expr parse:"0"];
- [self error:"More than MAXGRID points in x or y."];
- fclose(in);
- return self;
- }
- }
- qsort(x,nx,sizeof(float),comp);
- qsort(y,ny,sizeof(float),comp);
- rewind(in);
-
- /* 2nd pass, allocate memory,initialize and read data into array */
- p=pref[curPref].fileData=malloc(sizeof(Point)*nx*ny);
- pref[curPref].nfdata=nx*ny;
- for (i=0; i<nx; i++) {
- for (j=0; j<ny; j++) {
- p[i+nx*j].x=x[i];
- p[i+nx*j].y=y[j];
- p[i+nx*j].z=z0;
- }
- }
-
- for (i=0; i<cc; i++) fgets(s,240,in);
- while (fscanf(in,sc,&x0,&y0,&f)==3) {
- for (j=0; j<nx; j++) if (x0==x[j]) break;
- for (k=0; k<ny; k++) if (y0==y[k]) break;
- if (k==ny||j==nx) [self error:"Unusual error, notify author."];
- p[j+nx*k].z=f;
- }
- if (pref[curPref].data!=NULL) free(pref[curPref].data);
- pref[curPref].data=malloc(sizeof(Point)*pref[curPref].nfdata);
- pref[curPref].color=malloc(sizeof(RtColor)*pref[curPref].nfdata);
- [minX setFloatValue:x[0]];
- [minY setFloatValue:y[0]];
- [maxX setFloatValue:x[nx-1]];
- [maxY setFloatValue:y[ny-1]];
-
- /* equation is now used to modify data Z values, set initial formula for */
- /* z(x,y,z)=z. ie - for log plots you would enter "log(z)" */
- [equation setText:"z"];
- [pref[curPref].expr parse:"z"];
-
- /* update the display */
- [self setMinMax:self];
- [d3View zoom:self];
- return self;
- }
-
- /* return a data set to equation mode, free memory used by the file */
- -clearFile:sender
- {
- if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].fileData=NULL; }
- pref[curPref].nfdata=0;
-
- [equation setText:"0"];
- [pref[curPref].expr parse:"0"];
- [d3View zoom:self];
- return(self);
- }
-
- /* minz and maxz can be modified before returning, but currently aren't */
- -minmaxZ:(float *)minz :(float *)maxz
- {
- [dminZ setFloatValue:*minz];
- [dmaxZ setFloatValue:*maxz];
- if ([dzSwitch intValue]) {
- [minZ setFloatValue:*minz];
- [maxZ setFloatValue:*maxz];
- }
- *minz=[minZ floatValue];
- *maxz=[maxZ floatValue];
- return self;
- }
-
- /* display new min/max values (does not inform the views of the change) */
- -setMM:(float)minx :(float)maxx :(float)miny :(float)maxy
- {
- [minX setFloatValue:minx];
- [minY setFloatValue:miny];
- [maxX setFloatValue:maxx];
- [maxY setFloatValue:maxy];
- return self;
- }
-
- /* Tell the Plot3DView and (indirectly) the DensView about new max/min vals */
- -setMinMax:sender
- {
- [d3View zoomTo:[minX floatValue] :[minY floatValue] :[maxX floatValue] :[maxY floatValue]];
- [d3View zoom:self];
- return self;
- }
-
- /* zoom in by a fixed amount */
- -zoomIn:sender
- {
- float x,y,x1,y1;
- x1=[maxX floatValue];
- x=[minX floatValue];
- y1=[maxY floatValue];
- y=[minY floatValue];
-
- [maxX setFloatValue:x1-(x1-x)/4.0];
- [minX setFloatValue:x+(x1-x)/4.0];
- [maxY setFloatValue:y1-(y1-y)/4.0];
- [minY setFloatValue:y+(y1-y)/4.0];
-
- [self setMinMax:self];
- [d3View zoom:self];
- return self;
- }
-
- /* zoom out by a fixed amount */
- -zoomOut:sender
- {
- float x,y,x1,y1;
- x1=[maxX floatValue];
- x=[minX floatValue];
- y1=[maxY floatValue];
- y=[minY floatValue];
-
- [maxX setFloatValue:x1+(x1-x)/4.0];
- [minX setFloatValue:x-(x1-x)/4.0];
- [maxY setFloatValue:y1+(y1-y)/4.0];
- [minY setFloatValue:y-(y1-y)/4.0];
-
- [self setMinMax:self];
- [d3View zoom:self];
- return self;
- }
-
- /* sent by DensView, min/max are from 0.0 to 1.0, not real units */
- -zoomTo:(float)minx :(float)miny :(float)maxx :(float)maxy
- {
- float x0,x1,y0,y1;
-
- x0=[minX floatValue];
- x1=[maxX floatValue];
- y0=[minY floatValue];
- y1=[maxY floatValue];
-
- [minX setFloatValue:x0+(x1-x0)*minx];
- [minY setFloatValue:y0+(y1-y0)*miny];
- [maxX setFloatValue:x0+(x1-x0)*maxx];
- [maxY setFloatValue:y0+(y1-y0)*maxy];
- [self setMinMax:self];
- [d3View zoom:self];
- return self;
- }
-
- -dumpContour
- {
- [dView saveTiff:self];
- return self;
- }
-
- /* update the density plot */
- -updDen:(RtPoint)TickO :(RtPoint)TickS
- {
- static float *densData=NULL;
- static int ndd=0;
- int k,i,nx,ny;
- NXRect rec,rec2,tick;
- float x0=0,x1=0,y0=0,y1=0,zlim[4] = { -1.0,1.0,0,0};
- char s[80];
- float lev0,lev1;
-
- zlim[2]=[minZ floatValue];
- zlim[3]=[maxZ floatValue];
-
- if ([autoCont intValue]) {
- i=[[levels cellAt:2 :0] intValue];
- lev1=2.0/(float)i;
- lev0= -1.0+lev1/2.0;
- [[levels cellAt:0 :0] setFloatValue:(lev0+1.0)/2.0*
- (zlim[3]-zlim[2])+zlim[2]];
- [[levels cellAt:1 :0] setFloatValue:lev1/2.0*
- (zlim[3]-zlim[2])];
- }
- else {
- lev0=[[levels cellAt:0 :0] floatValue];
- lev1=[[levels cellAt:1 :0] floatValue];
- lev0=(lev0-zlim[2])/(zlim[3]-zlim[2])*2.0-1.0;
- lev1=lev1/(zlim[3]-zlim[2])*2.0;
- }
-
- if (lev1<=0) lev1=.2;
- [[d3View worldShape] setContour:lev0/2.0+.5 :lev1/2.0];
-
- tick.origin.x=(TickO[0]+1.0)/2.0;
- tick.origin.y=(TickO[1]+1.0)/2.0;
- tick.size.width=TickS[0]/2.0;
- tick.size.height=TickS[1]/2.0;
-
- rec2.origin.x=[minX floatValue];
- rec2.origin.y=[minY floatValue];
- rec2.size.width=[maxX floatValue]-[minX floatValue];
- rec2.size.height=[maxY floatValue]-[minY floatValue];
- rec=rec2;
- if (pref[curPref].ndata==0) {
- [dView setData:0 :0 :NULL :zlim :tick :rec :rec2 :lev0 :lev1];
- return self;
- }
-
- nx=pref[curPref].nx;
- ny=pref[curPref].ny;
- if (ndd<(nx*ny)) {
- if (densData!=NULL) free(densData);
- densData=malloc(nx*ny*sizeof(float));
- ndd=nx*ny;
- }
-
- if (pref[curPref].fileData==NULL||nx*ny==pref[curPref].ndata) {
- for (k=0; k<pref[curPref].ndata; k++) densData[k]=pref[curPref].data[k].z;
- }
- else {
- sprintf(s,"Error nx*ny=%d ndata=%d\n",nx*ny,pref[curPref].ndata);
- [self error:s];
- /* for (k=0; k<(nx*ny); k++) densData[k]= -.5;
- for (k=0; k<pref[curPref].ndata; k++) {
- i=floor((pref[curPref].data[k].x+.5)*(float)nx)+
- floor((pref[curPref].data[k].y+.5)*(float)ny)*nx;
- if (i>=0 && i<ndd) densData[i]=pref[curPref].data[k].z;
- }*/
- }
-
- if (pref[curPref].fileData!=NULL) {
- for (i=0; i<pref[curPref].nfdata; i++) {
- x0=pref[curPref].fileData[i].x;
- y0=pref[curPref].fileData[i].y;
- if (x0>=rec2.origin.x && y0>=rec2.origin.y) break;
- }
- for (i=pref[curPref].nfdata-1; i>=0; i--) {
- x1=pref[curPref].fileData[i].x;
- y1=pref[curPref].fileData[i].y;
- if (x1<=rec2.origin.x+rec2.size.width &&
- y1<=rec2.origin.y+rec2.size.height) break;
- }
-
- rec.size.width=x1-x0;
- rec.origin.x=x0;
- rec.size.height=y1-y0;
- rec.origin.y=y0;
- }
-
- if (pref[curPref].sym!= -1) [dView setData:nx :ny :densData :zlim :tick :rec :rec2 :lev0 :lev1];
- else [dView setData:0 :0 :NULL :zlim :tick :rec :rec2 :lev0 :lev1];
- return self;
- }
-
- int comp(float *x,float *y)
- {
- if (x<y) return(-1);
- if (y>x) return(1);
- return (0);
- }
-
- -newInsp:sender
- {
- int i;
-
- i=[[sender selectedCell] tag];
- switch(i) {
- case 0: [I_BOX setContentView:I_lim];
- break;
- case 1: [I_BOX setContentView:I_dis];
- break;
- case 2: [I_BOX setContentView:I_pho];
- break;
- }
- [I_BOX display];
- return self;
- }
-
- /* variable slider changed */
- -setVarS:sender
- {
- int i;
-
- for (i=0; i<5; i++)
- [[varText cellAt:i :0] setFloatValue:[[varSli cellAt:i :0] floatValue]];
- [d3View zoom:self];
- return self;
- }
-
- /* variable text changed */
- -setVarT:sender
- {
- int i;
- for (i=0; i<5; i++)
- [[varSli cellAt:i :0] setFloatValue:[[varText cellAt:i :0] floatValue]];
- [d3View zoom:self];
- return self;
- }
-
- /* new var min/max */
- -setVarMinMax:sender
- {
- int i;
-
- for (i=0; i<5; i++)
- [[[varSli cellAt:i :0] setMaxValue:[[varMax cellAt:i :0] floatValue]] setMinValue:[[varMin cellAt:i :0] floatValue]];
- return self;
- }
-
- -saveData:sender
- {
- id pan;
- FILE *out;
- int i;
- float x0,x1,y0,y1,z0,z1;
- x0=[minX floatValue];
- x1=[maxX floatValue]-x0;
- y0=[minY floatValue];
- y1=[maxY floatValue]-y0;
- z0=[minZ floatValue];
- z1=[maxZ floatValue]-z0;
-
- pan=[SavePanel new];
- if ([pan runModal]) {
- out=fopen([pan filename],"w");
- fprintf(out,"# Created by Plot3D\n");
- for (i=0; i<pref[curPref].ndata; i++)
- fprintf(out,"%f\t%f\t%f\n",(pref[curPref].data[i].x/2.0+.5)*x1+x0,
- (pref[curPref].data[i].y/2.0+.5)*y1+y0,
- (pref[curPref].data[i].z/2.0+.5)*z1+z0);
- fclose(out);
- }
- return self;
- }
-
- /* Start rendering an animation */
- -makeAnim:sender
- {
- int afl=0,n=16,cf;
- static id savePanel=nil;
- float chi,chistp,theta,t,tstp;
- char animFile[100]; /* animation directory */
- char animName[30]; /* animation name */
- char fsp[MAXPATHLEN];
- int i,j=0;
-
- if (!savePanel) {
- savePanel=[SavePanel new];
- [savePanel setRequiredFileType:"anim"];
- }
-
- if(![savePanel runModal]) return self;
- if (strlen([savePanel filename])>78) {
- [self error:"Filespec too long. Please notify author."];
- return self;
- }
- strcpy(animFile, [savePanel filename]);
- mkdir(animFile,0777);
- for (i=strlen(animFile)-1; i>=0; i--) if (animFile[i]=='/') break;
- i++;
- while (i<strlen(animFile)-5) animName[j++]=animFile[i++];
- animName[j]=0;
- afl=[[animFlag cellAt:0 :0] intValue]*ANIM_spin+
- [[animFlag cellAt:1 :0] intValue]*ANIM_t;
- if (afl==0) {
- [self error:"Animation doesn't do anything!"];
- return self;
- }
- n=[animFrames intValue];
- chistp=M_PI*2.0/(float)n;
- chi=[d3View getChi];
- theta=[d3View getTheta];
- t=[[varMin cellAt:0 :0] floatValue];
- tstp=([[varMax cellAt:0 :0] floatValue]-t)/(float)(n-1);
-
- for (cf=0; cf<n; cf++) {
- [[varText cellAt:0 :0] setFloatValue:t];
- [[varSli cellAt:0 :0] setFloatValue:t];
- [d3View setAng:theta :chi];
- [d3View zoom:self];
- sprintf(fsp,"%s/%s.%d.tiff",animFile,animName,cf+1);
- [self message:"Rendering animation. This will take a while ..." :fsp];
- [d3View renderTIFF:fsp];
- if (afl&ANIM_t) t+=tstp;
- if (afl&ANIM_spin) chi+=chistp;
- }
- [self message:"Rendering complete !!!" :"(use Movie.app or a similar program to view)"];
- return self;
- }
-
- -error:(char *)msg
- {
- [errTitle setStringValue:"ERROR"];
- [errMsg setStringValue:msg];
- [errPan makeKeyAndOrderFront:self];
- return self;
- }
-
- -message:(char *)s1 :(char *)s2
- {
- [errTitle setStringValue:s1];
- [errMsg setStringValue:s2];
- [errPan makeKeyAndOrderFront:self];
- return self;
- }
-
- @end
-